package com.wonderful.eyepetizer.data.repo

import android.util.Log
import com.google.gson.JsonParseException
import com.wonderful.eyepetizer.data.entity.response.Resource
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.withContext
import org.apache.http.conn.ConnectTimeoutException
import org.json.JSONException
import retrofit2.HttpException
import java.io.IOException
import java.net.SocketTimeoutException
import java.net.UnknownHostException

/**
 * Desc:
 * @Author: wonderful
 * @Time: 2024/1/23 16:14
 */
open class BaseRepo {
    suspend inline fun <T> executeHttp(crossinline block: suspend CoroutineScope.() -> T): Resource<T> {
        return withContext(Dispatchers.IO) {
            val res: Resource<T>
            try {
                // todo 还需处理 code != 200 的请求失败情况
                res = Resource.success(block())
            } catch (e: Throwable) {
                return@withContext ApiException.build(e).toResponse()
            }
            if (res.code == ApiException.CODE_AUTH_INVALID) {
                Log.e("ApiCaller", "request auth invalid")
                // 登录过期，取消协程，跳转登录界面
                // 省略部分代码
                cancel()
            }
            return@withContext res
        }
    }

    class ApiException(
        val code: Int,
        override val message: String,
        override val cause: Throwable? = null
    ) : RuntimeException(message, cause) {
        companion object {
            // 网络状态码
            const val CODE_NET_ERROR = 4000
            const val CODE_TIMEOUT = 4080
            const val CODE_JSON_PARSE_ERROR = 4010
            const val CODE_SERVER_ERROR = 5000

            // 业务状态码
            const val CODE_AUTH_INVALID = 401

            fun build(e: Throwable): ApiException {
                return when (e) {
                    is HttpException -> {
                        ApiException(CODE_NET_ERROR, "网络异常(${e.code()},${e.message()})")
                    }

                    is UnknownHostException -> {
                        ApiException(CODE_NET_ERROR, "网络连接失败，请检查后再试")
                    }

                    is ConnectTimeoutException, is SocketTimeoutException -> {
                        ApiException(CODE_TIMEOUT, "请求超时，请稍后再试")
                    }

                    is IOException -> {
                        ApiException(CODE_NET_ERROR, "网络异常(${e.message})")
                    }

                    is JsonParseException, is JSONException -> {
                        // Json解析失败
                        ApiException(CODE_JSON_PARSE_ERROR, "数据解析错误，请稍后再试")
                    }

                    else -> {
                        ApiException(CODE_SERVER_ERROR, "系统错误(${e.message})")
                    }
                }
            }
        }

        fun <T> toResponse(): Resource<T> {
            return Resource.error(message, code)
        }
    }
}